# Moths - an environment for mathy calculations
# Copyright (C) 2006 Mike Sutjipto
# Licensed under the GPL

module Moths
  
  # Operation is a type of expression that represents
  # an operation (addition, subtractions, etc)
  #
  class Operation < Expression
    @op_type
    @left_child
    @right_child
        
    attr_reader :left_child, :right_child
    attr_writer :left_child, :right_child

    def initialize(op_type, left_child, right_child)
      @op_type = op_type
      @left_child = left_child
      @right_child = right_child

      # set the precedence for this node
      case @op_type
        when :exp
          @precedence = 5

        when :div, :times
          @precedence = 4

        when :plus, :minus
          @precedence = 2
        else
          raise MothsError, 'unknown op'
      end
    end

    def eval(env)
      left = @left_child.eval(env)
      right = @right_child.eval(env)

      if left.num_type != right.num_type then
        num_type = :integer
      else
        num_type = left.num_type # left is arbitrary - right works too
      end

      # TODO abstract these operations
      case @op_type
        when :plus
          return Number.new(num_type, left.num + right.num)
        when :minus
          return Number.new(num_type, left.num - right.num)
        when :times
          return Number.new(num_type, left.num * right.num)
        when :div
          return Number.new(num_type, left.num / right.num)
        when :exp
          return Number.new(num_type, left.num ** right.num)
        else
          raise MothsError, 'Unknown operation type (omg what is this): ' + @opType.to_s
      end
    end

    def to_s
      return '( ' + @leftChild.to_s + ' ' + @opType.to_s + ' ' + @rightChild.to_s + ' )'
    end

  end
  
end
